-- EEPROM功能测试
-- 2021.05.07
-- Lingd
-- 福州泰诚网络科技有限公司
module(...,package.seeall)

require"pins"
require"bit"
require"tool"

local I2C_WR        = 0                         -- 写控制bit
local I2C_RD        = 1                         -- 读控制bit
local EE_DEV_ADDR   = 0xA0                      -- 24xx02的设备地址
local EE_PAGE_SIZE  = 8                         -- 24xx02的页面大小
local EE_SIZE       = 256                       -- 24xx02总容量

local I2C_SCL       = pins.setup(pio.P0_14, 1)  -- 脉冲输出

-- 全局变量（分别为：电压校准值、1路-8路电流校准值）
--local RegCRes = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}

local function delay()
	local i = 0
	for i = 0,3000 do end
end

-- 发起I2C总线启动信号
local function Start()
	local I2C_SDA = pins.setup(pio.P0_15, 1)  -- 数据输出
    I2C_SDA(1)
    I2C_SCL(1)
	delay()
    I2C_SDA(0)
	delay()
    I2C_SCL(0)
	delay()
end

-- 发起I2C总线停止信号
local function Stop()
	local I2C_SDA = pins.setup(pio.P0_15, 0)  -- 数据输出
    I2C_SCL(0)
    I2C_SDA(0)
	delay()
    I2C_SCL(1)
	delay()
    I2C_SDA(1)
	delay()
end

-- 产生一个时钟，并读取器件的ACK应答信号
local function WaitAck()
    local AckState,i = 0,0
	local I2C_SDA = pins.setup(pio.P0_15, 0)  -- 数据输出

	I2C_SDA(1)
	delay()
    I2C_SCL(1)
	delay()
	local I2C_SDA_IN = pins.setup(pio.P0_15)     -- 数据输入
	for i = 0,1000 do
		if (I2C_SDA_IN() == 0) then
			AckState = 0
			break
		end
	end
    I2C_SCL(0)
	delay()

    return AckState
end

-- 产生一个ACK信号
local function SendAck()
	local I2C_SDA       = pins.setup(pio.P0_15, 0)  -- 数据输出
    I2C_SDA(0)
	delay()
    I2C_SCL(1)
	delay()
    I2C_SCL(0)
	delay()
	I2C_SDA(1)
end

-- 产生1个NACK信号
local function SendNoAck()
	local I2C_SDA       = pins.setup(pio.P0_15, 1)  -- 数据输出
    I2C_SDA(1)
	delay()
    I2C_SCL(1)
	delay()
    I2C_SCL(0)
	delay()
end

-- 向I2C总线设备发送8bit数据
local function SendByte(Dat)
	local i = 0
	local I2C_SDA = pins.setup(pio.P0_15, 1)  -- 数据输出

	I2C_SCL(0)
    for i = 0,7 do
        if bit.band(bit.lshift(Dat,i),0x80) == 0x00 then
            I2C_SDA(0)
        else
            I2C_SDA(1)
        end
		delay()
        I2C_SCL(1)
		delay()
        I2C_SCL(0)
		delay()
    end  
end
 
-- 从I2C总线设备读取8bit数据
local function ReadByte()
	local i,Dat = 0,0
	local I2C_SDA_IN = pins.setup(pio.P0_15)     -- 数据输入
	I2C_SDA_IN()
	
	for i = 0,7 do
        Dat = bit.lshift(Dat,1)
		I2C_SCL(1)
		delay()
		if (I2C_SDA_IN() == 1) then
			Dat = Dat + 1
        end
		I2C_SCL(0)
		delay()
	end

	return Dat
end

-- 检测I2C总线设备，CPU向发送设备地址，然后读取设备应答来判断该设备是否存在
local function CheckDevice(Addr)
	local Ack = 0

	Start()
	SendByte(bit.bor(Addr,I2C_WR))
	Ack = WaitAck()
	Stop()

	return Ack
end

-- 判断串行EERPOM是否正常 1 表示正常， 0 表示不正常
local function CheckOk()
    if (CheckDevice(EE_DEV_ADDR) == 0) then
        return 1
    else
        Stop()		
        return 0
    end
end

-- 向串行EEPROM指定地址写入若干数据，采用页写操作提高写入效率
function WriteBytes(Addr,Data)
	local i,m = 0,0

	for i = 1,#Data do
		if ((i == 1) or (bit.band(Addr,EE_PAGE_SIZE-1) == 0)) then
			Stop()
			
			-- 写入命令
			Start()
			
			SendByte(bit.bor(EE_DEV_ADDR,I2C_WR))		  
			
			if (WaitAck() == 1) then
				Stop()
				return 0                    
			end

			-- 写入地址
			SendByte(Addr)
			
			if (WaitAck() == 1) then
				Stop()
				return 0                        
			end				
		end
	
		-- 写入数据
		SendByte(Data[i])
	
		if (WaitAck() == 1) then
            Stop()
            return 0
        end

		Addr = Addr+1											
	end

	Stop()
	return 1
end

-- 从串行EEPROM指定地址处开始读取若干数据
function ReadBytes(Addr,Len)
	local i,ReadBuf = 1,{}

	-- 写入命令
	Start()
	
	SendByte(bit.bor(EE_DEV_ADDR,I2C_WR))		  
	
	if (WaitAck() == 1) then
        Stop()
	    return ReadBuf                    
    end

	-- 写入地址
	SendByte(Addr)
	
	if (WaitAck() == 1) then
        Stop()
	    return ReadBuf                        
    end
	
	-- 写入命令，开始读
	Start()
	
	SendByte(bit.bor(EE_DEV_ADDR,I2C_RD))		  
	
	if (WaitAck() == 1) then				
        Stop()
	    return ReadBuf                         
    end

	-- 读取数据
	for i = 1,Len do
		ReadBuf[i] = ReadByte()
		if Len ~= i then
			SendAck()
		else
			SendNoAck()
		end
	end
	
	Stop()
	log.info("ReadBuf",tool.HextoHexStr(ReadBuf," "))
	return ReadBuf		
end

-- EEPROM全部写0
function Erase()
	local i,buf = 0,{}
	
	for i = 1,EE_SIZE do
		buf[i] = 0x00
    end
	
	if (WriteBytes(0,buf) == 0)	then
        return
    end
end

function ReadRegCRes()
	return ReadBytes(0x00,36)
end

--local w_data = {0xF5,0x0B,0x5F,0x26,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07,0x98,0x63,0xAA,0x07}

sys.taskInit(function()
	--sys.wait(5000)
	--Erase()
    --log.info("state",WriteBytes(0x00,w_data))
    --ReadRegCRes()
	--log.info("eeprom data",tool.HextoHexStr(RegCRes," "))
end)




